using System;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Peak.Can.Basic;
using System.IO.Ports;
using TPCANHandle = System.Byte;


namespace WinCANTool
{
    partial class MDIWindow
    {
        public long StartTime;
        
        private byte m_hClient = 0;  /* Client Handle   */
        private byte m_hNet = 0;     /* Network Handle  */
        private byte m_hHw = 0;      /* Hardware Handle */
		private SerialPort m_hLindeHw;
		
        struct NetParams
        {
            public bool NetsNotConnected;
            public TPCANBaudrate BaudRate;
            public TPCANHandle m_PcanHandle;
            public string ErrorString;
			public TPCANType m_HwType;	
			public string m_Port;
        }
        NetParams Net = new NetParams();

        public uint[] BaudRates =  {0x0014,         //   1 MBit/s
                                0x001C,             // 500 kBit/s
                                0x011C,             // 250 kBit/s
                                0x031C,             // 125 kBit/s
                                0x432F,             // 100 kBit/s
                                0x472F,             //  50 kBit/s
                                0x532F,             //  20 kBit/s
                                0x672F,             //  10 kBit/s
                                0x7F7F};            //   5 kBit/s

        public string[] BaudRateText = {"1 MBit/sec",
                                    "500 kBit/sec",
                                    "250 kBit/sec",
                                    "125 kBit/sec",
                                    "100 kBit/sec",
                                    "50 kBit/sec",
                                    "20 kBit/sec",
                                    "10 kBit/sec",
                                    "5 kBit/sec" };
        
        
        private void NetInit()
        {
            Net.NetsNotConnected = true;
            Net.BaudRate = TPCANBaudrate.PCAN_BAUD_500K;
            Net.ErrorString = "";
			Net.m_PcanHandle = PCANBasic.PCAN_USBBUS1;
			Net.m_HwType = TPCANType.PCAN_TYPE_ISA;
			Net.m_Port = CurrentOptions.port;
        }

        private void FactoryUserInit(bool FactoryUserOn)
        {
            if (FactoryUserOn)
            {
                EnterNewSymbolMenu.Visible = true;
                EnterRawMenu.Visible = true;
                newMessageToolStripMenuItem.Visible = true;
                OpenTraceMenu.Visible = true;
                openTraceWindowToolStripMenuItem.Visible = true;

            }
            else
            {
                EnterNewSymbolMenu.Visible = false;
                EnterRawMenu.Visible = false;
                newMessageToolStripMenuItem.Visible = false;
                OpenTraceMenu.Visible = false;
                openTraceWindowToolStripMenuItem.Visible = false;
            }

        }


        private void InitializeLocalSystemTime()
        {
            //TPCANTimestamp tstamp;
            //long SystemTimeMs = 0;

            //CanApi2.GetSystemTime(out tstamp);
            //DateTime LocalTime = DateTime.Now;
            //SystemTimeMs = (long)tstamp.millis;
            //StartTime = LocalTime.Ticks - 10000 * SystemTimeMs;
        }


        private void connectToNet(object sender, EventArgs e)
        {
            //string strClientName = "Linde CAN Tool v.1";

			 Net.NetsNotConnected = true;


	         Thread.Sleep(1000);


            if (Net.NetsNotConnected)
            {
               // uint ret = CanApi2.RegisterClient(strClientName, (uint)Handle.ToInt32(), out m_hClient);
               // if (ret == CanApi2.ERR_OK)
                {
                    if (NetConnect())
                    {
                        newMDIChild1.StartThreads();
                        SetupStatusLabel(true);
                        newMDIChild1.mdi_thread.Start();
                        newMDIChild1.m_thread.Start();
                        Net.NetsNotConnected = false;
                       // int TempInt = (int)BaudRates[CurrentOptions.BaudIndex];
                       // SetNetBaudRate(TempInt);
                        DisplayCurrentBaudRate();
                        newMDIChild1.NetStatus.Text = "> CanApi2.RegisterClient() succeeded.";
                    }
                }
                //else
                //{
                //    SetupStatusLabel(false);
                //    newMDIChild1.NetStatus.Text = "> CanApi2.RegisterClient() failed.\r\n> ERROR: " + ErrorMessage(ret);
                //    Net.ErrorString += newMDIChild1.NetStatus.Text;
                    
                //}
            }

            if(Net.NetsNotConnected)
                MessageBox.Show(Net.ErrorString,"Connect Error");

        }


        private void connectToLindeCan(object sender, EventArgs e)
        {
			 Net.NetsNotConnected = true;
	         Thread.Sleep(1000);
            if (Net.NetsNotConnected)
            {
                if (LindeCanConnect())
                {
                    newMDIChild1.StartLindeCanThreads();
                    SetupStatusLabel(true);
                    newMDIChild1.mdi_thread.Start();
                    newMDIChild1.m_thread.Start();
                    Net.NetsNotConnected = false;
                    DisplayCurrentBaudRate();
                    newMDIChild1.NetStatus.Text = "> Linde Can.RegisterClient() succeeded.";
                }
            }

            if(Net.NetsNotConnected)
        	{
	            //MessageBox.Show(Net.ErrorString,"Linde Can Connect Error");
        	}

        }		

        
        private bool NetReset()
        {
            //
            
            //uint ret = CanApi2.ResetHardware((byte)m_hHw);

            //if (ret == CanApi2.ERR_OK)
            //    return true;
            //else
            //    return false;
            return true;
         
        }

        /// <summary>
        /// Activates/deaactivates the different controls of the main-form according
        /// with the current connection status
        /// </summary>
        /// <param name="bConnected">Current status. True if connected, false otherwise</param>
        private void SetConnectionStatus(bool bConnected)
        {
            // Buttons

        }

        /// <summary>
        /// Includes a new line of text into the information Listview
        /// </summary>
        /// <param name="strMsg">Text to be included</param>
        private void IncludeTextMessage(string strMsg)
        {
            //lbxInfo.Items.Add(strMsg);
           // lbxInfo.SelectedIndex = lbxInfo.Items.Count - 1;
        }
		

        /// <summary>
        /// Help Function used to get an error as text
        /// </summary>
        /// <param name="error">Error code to be translated</param>
        /// <returns>A text with the translated error</returns>
        private string GetFormatedError(TPCANStatus error)
        {
            StringBuilder strTemp;

            // Creates a buffer big enough for a error-text
            //
            strTemp = new StringBuilder(256);
            // Gets the text using the GetErrorText API function
            // If the function success, the translated error is returned. If it fails,
            // a text describing the current error is returned.
            //
            if (PCANBasic.GetErrorText(error, 0, strTemp) != TPCANStatus.PCAN_ERROR_OK)
                return string.Format("An error occurred. Error-code's text ({0:X}) couldn't be retrieved", error);
            else
                return strTemp.ToString();
        }

        /// <summary>
        /// Configures the PCAN-Trace file for a PCAN-Basic Channel
        /// </summary>
        private void ConfigureTraceFile()
        {
            UInt32 iBuffer;
            TPCANStatus stsResult;

            // Configure the maximum size of a trace file to 5 megabytes
            //
            iBuffer = 5;
            stsResult = PCANBasic.SetValue(Net.m_PcanHandle, TPCANParameter.PCAN_TRACE_SIZE, ref iBuffer, sizeof(UInt32));
            if (stsResult != TPCANStatus.PCAN_ERROR_OK)
                IncludeTextMessage(GetFormatedError(stsResult));            

            // Configure the way how trace files are created: 
            // * Standard name is used
            // * Existing file is ovewritten, 
            // * Only one file is created.
            // * Recording stopts when the file size reaches 5 megabytes.
            //
            iBuffer = PCANBasic.TRACE_FILE_SINGLE | PCANBasic.TRACE_FILE_OVERWRITE;
            stsResult = PCANBasic.SetValue(Net.m_PcanHandle, TPCANParameter.PCAN_TRACE_CONFIGURE, ref iBuffer, sizeof(UInt32));
            if (stsResult != TPCANStatus.PCAN_ERROR_OK)
                IncludeTextMessage(GetFormatedError(stsResult));   
        }
		
        
        private bool NetConnect()
        {

			TPCANStatus stsResult;
            bool NetConnectOn = true;
            UInt32 iBuffer;
		

			// Connects a selected PCAN-Basic channel
			//
			stsResult = PCANBasic.Initialize(
											Net.m_PcanHandle, 
											Net.BaudRate, 
											Net.m_HwType, 
											Convert.ToUInt32("0100",16), 
											Convert.ToUInt16("3"));

			if (stsResult != TPCANStatus.PCAN_ERROR_OK)
				MessageBox.Show(GetFormatedError(stsResult));
			else
			// Prepares the PCAN-Basic's PCAN-Trace file
			//
				ConfigureTraceFile();

			// Sets the connection status of the main-form
			//
			SetConnectionStatus(stsResult == TPCANStatus.PCAN_ERROR_OK);


			

		
            // Init for errormessage
           // StringBuilder errText = new StringBuilder();
           // string net = "TestNet";
           // bool NetConnectOn = true;

            // Connect to net
            //uint ret = CanApi2.ConnectToNet(m_hClient, net, out m_hNet);
            if (stsResult == TPCANStatus.PCAN_ERROR_OK)
            {
                newMDIChild1.NetStatus.Text = "> CanApi2.ConnectToNet(\"TestNet\") succeeded.";


                // Setting the message filter
                // Initialize message filter 1 and 2
               // TCANMsg msg1 = new PCANBasic.TCANMsg();
               // PCANBasic.TCANMsg msg2 = new PCANBasic.TCANMsg();
               // msg1.ID = 0x000;
               // msg2.ID = 0x7ff;

                // In the beginning you must set the range of the message filter.
                // There are two different ways:
                // - RegisterMsg 
                // - SetClientFilter

                // RegisterMsg
                //ret = CanApi2.RegisterMsg(m_hClient, m_hNet, ref msg1, ref msg2);

                // SetClientFilter (in this example all messages will be accepted)
                // Please comment out the RegisterMsg method.
                 stsResult = PCANBasic.FilterMessages(
                 Net.m_PcanHandle,
                 Convert.ToUInt32(0x793),
                 Convert.ToUInt32(0x793),
                 TPCANMode.PCAN_MODE_STANDARD);


                // Error handling
                if (stsResult == TPCANStatus.PCAN_ERROR_OK)
                {
                    newMDIChild1.NetStatus.Text = "> The filter was customized. IDs from 0 to 0x7ff will be received";

                }
                else
                {
                    newMDIChild1.NetStatus.Text = "> PCANBasic.FilterMessages failed.\r\n> ERROR: " + GetFormatedError(stsResult)+ "\r\n";
                    Net.ErrorString += newMDIChild1.NetStatus.Text;
                    NetConnectOn = false;
                }

                iBuffer = PCANBasic.PCAN_FILTER_OPEN;
               stsResult = PCANBasic.SetValue(
                Net.m_PcanHandle, 
                TPCANParameter.PCAN_MESSAGE_FILTER, 
                ref iBuffer, 
                sizeof(UInt32));

            // If success, an information message is written, if it is not, an error message is shown
            //
               if (stsResult == TPCANStatus.PCAN_ERROR_OK)
               {
                   ;
               }
               //IncludeTextMessage(string.Format("The filter was successfully {0}", rdbFilterClose.Checked ? "closed." : "opened."));
               else
                   MessageBox.Show(GetFormatedError(stsResult));
				

                // Get hardware handle

                //int nHw;
                //ret = CanApi2.GetNetParam(m_hNet, CanApi2.PARAM_NETHW, out nHw, 0);
                //if (ret == CanApi2.ERR_OK)
                //{
                //    m_hHw = (byte)nHw;
                //    newMDIChild1.NetStatus.Text = "> CanApi2.GetNetParam() succeeded.";
                //    SetNetHandle(m_hNet);
                //    SetHwHandle(m_hHw);

                //}
                //else
                //{
                //    newMDIChild1.NetStatus.Text = "> CanApi2.GetNetParam() failed.\r\n> ERROR: " + ErrorMessage(ret) + "\r\n";
                //    Net.ErrorString += newMDIChild1.NetStatus.Text;
                //    NetConnectOn = false;
                //}

                //SetClientHandle(m_hClient);
                //SetNetHandle(m_hNet);
            }
            else
            {
                newMDIChild1.NetStatus.Text = "> CanApi2.ConnectToNet() failed.\r\n> ERROR: ";
                Net.ErrorString += newMDIChild1.NetStatus.Text;
                NetConnectOn = false;
            }

            return NetConnectOn;

        }


        private bool LindeCanConnect()
        {
		    m_hLindeHw = new SerialPort();
			m_hLindeHw.PortName = Net.m_Port;
			m_hLindeHw.BaudRate = 115200;
			m_hLindeHw.Parity = Parity.None;
			m_hLindeHw.StopBits = StopBits.One;

            string[] ports = SerialPort.GetPortNames();

            int index = Array.IndexOf(ports, m_hLindeHw.PortName);
            

			if(index < 0)
			{
	            newMDIChild1.NetStatus.Text = "> Linde Can.ConnectToNet(\"TestNet\") fail.";
                return false;
			}
			else
			{
	            m_hLindeHw.Open();
				newMDIChild1.EnableReadSNButton();
				newMDIChild1.EnableValidateButton();
				
	            newMDIChild1.NetStatus.Text = "> Linde Can.ConnectToNet(\"TestNet\") succeeded.";
				
			}
			

            return true;
        }


        private void disconnectFromNetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            byte Client = GetClientHandle();
            byte hnet = GetNetHandle();

            //CanApi2.DisconnectFromNet(Client, hnet);
            //CanApi2.RemoveClient(Client);
            Net.NetsNotConnected = true;
            SetupStatusLabel(false);
            // End thread
            newMDIChild1.StopThread();

        }



        //// Method ErrorMessage
        private static string ErrorMessage(uint CANResult)
        {
            StringBuilder errText = new StringBuilder();
            //CanApi2.GetErrText(CANResult, errText);
            return (errText.ToString());
        }

        public int GetNetBaudRate()
        {
            int Baud = 1;
            byte hNet = GetNetHandle();

            //CanApi2.GetNetParam(hNet, CanApi2.PARAM_BAUDRATE, out Baud, 0);
            return Baud;
        }

        public void TurnOnErrorFrames(bool TurnOn)
        {
            if (!Net.NetsNotConnected)
            {
                byte hClient = GetClientHandle();
                byte hHw = GetHwHandle();


                //CanApi2.SetClientParam(hClient, CanApi2.PARAM_RCVERRFRAMES, OnValue);
                
            }
        }
        
        public void SetNetBaudRate(int Baud)
        {
            byte hHw;

            if (Net.NetsNotConnected)
                return;
            
            hHw = GetHwHandle();
           // CanApi2.SetHwParam(hHw, CanApi2.PARAM_BAUDRATE, (uint)Baud);
          //  DisplayBaudRate(Baud);

        }

        public void DisplayCurrentBaudRate()
        {
            int Baud;

            if (Net.NetsNotConnected)
                return;
            Baud = GetNetBaudRate();
            DisplayBaudRate(Baud);
        }
        
        
        public void DisplayBaudRate(int Baud)
        {


            CurrentOptions.BaudIndex = Array.IndexOf(BaudRates, (uint) Baud);

            Baud1M.Checked = false;
            Baud500.Checked = false;
            Baud250.Checked = false;
            Baud125.Checked = false;
            Baud100.Checked = false;
            Baud50.Checked = false;
            Baud20.Checked = false;
            Baud10.Checked = false;


            switch(CurrentOptions.BaudIndex)
            {
                case 7:
                    {
			            Net.BaudRate = TPCANBaudrate.PCAN_BAUD_10K;
                        BaudRateSelect.Text = "10K Baud";
                        Baud10.Checked = true;
                        break;
                    }

                case 6:
                    {
			            Net.BaudRate = TPCANBaudrate.PCAN_BAUD_20K;
                        BaudRateSelect.Text = "20K Baud";
                        Baud20.Checked = true;
                        break;
                    }

                case 5:
                    {
			            Net.BaudRate = TPCANBaudrate.PCAN_BAUD_50K;
                        BaudRateSelect.Text = "50K Baud";
                        Baud50.Checked = true;
                        break;
                    }

                case 4:
                    {
			            Net.BaudRate = TPCANBaudrate.PCAN_BAUD_100K;
                        BaudRateSelect.Text = "100K Baud";
                        Baud100.Checked = true;
                        break;
                    }

                case 3:
                    {
			            Net.BaudRate = TPCANBaudrate.PCAN_BAUD_125K;
                        BaudRateSelect.Text = "125K Baud";
                        Baud125.Checked = true;
                        break;
                    }
                case 2:
                    {
			            Net.BaudRate = TPCANBaudrate.PCAN_BAUD_250K;
                        BaudRateSelect.Text = "250K Baud";
                        Baud250.Checked = true;
                        break;
                    }
                case 1:
                    {
			            Net.BaudRate = TPCANBaudrate.PCAN_BAUD_500K;
                        BaudRateSelect.Text = "500K Baud";
                        Baud500.Checked = true;
                        break;
                    }
                case 0:
                    {
			            Net.BaudRate = TPCANBaudrate.PCAN_BAUD_1M;
                        BaudRateSelect.Text = "1 M Baud";
                        Baud1M.Checked = true;
                        break;
                    }

            }

        }


        private void Baud1M_Click(object sender, EventArgs e)
        {
           // SetNetBaudRate(CanApi2.BAUD_1M);
        }
        
        private void Baud500Selected(object sender, EventArgs e)
        {
            //SetNetBaudRate(CanApi2.BAUD_500K);
        }

        private void Baud250Selected(object sender, EventArgs e)
        {
            //SetNetBaudRate(CanApi2.BAUD_250K);
        }

        private void Baud125Select(object sender, EventArgs e)
        {
            //SetNetBaudRate(CanApi2.BAUD_125K);
        }
        
        
        private void Baud100_Click(object sender, EventArgs e)
        {
            //SetNetBaudRate(CanApi2.BAUD_100K);
        }
        
        private void Baud50_Click(object sender, EventArgs e)
        {
            //SetNetBaudRate(CanApi2.BAUD_50K);
        }

        private void Baud20_Click(object sender, EventArgs e)
        {
           // SetNetBaudRate(CanApi2.BAUD_20K);
        }

        private void Baud10_Click(object sender, EventArgs e)
        {
            //SetNetBaudRate(CanApi2.BAUD_10K);
        }



        public TPCANHandle GetClientHandle()
        {
            return Net.m_PcanHandle;
        }

        public byte GetNetHandle()
        {
            return m_hNet;
        }


        public SerialPort GetSerialHandle()
        {
            return m_hLindeHw;
        }
        public byte GetHwHandle()
        {
            return m_hHw;
        }

        public void SetClientHandle(byte Input)
        {
            m_hClient = Input;
        }

        public void SetNetHandle(byte Input)
        {
            m_hNet = Input;
        }

        public void SetHwHandle(byte Input)
        {
            m_hHw = Input;
        }

        public int GetCurrentBaudRate()
        {
            return (int)Net.BaudRate;
        }
        
        public uint[] GetBaudValues()
        {
            return BaudRates;
        }

        public string[] GetBaudStrings()
        {
            return BaudRateText;
        }
        
        
        
        
        public void GetOptions()
        {
            ReadOptionsIni NewIni = new ReadOptionsIni();
            if (!NewIni.GetInitOptions(ref CurrentOptions, CurrentPath))
            {
                SetDefaultOptions();
                NewIni.WriteFile(ref CurrentOptions, CurrentPath);

            }

        }

        public void SetDefaultOptions()
        {
            CurrentOptions.BaudIndex = 3;
            CurrentOptions.MainFileName = "Browse for file";
            CurrentOptions.MainNodeID = "783";
   		    CurrentOptions.hardware = 2; 
			CurrentOptions.port = "COM3"; 
			CurrentOptions.serial_number = "-1";
			CurrentOptions.security_key = "-1";
        }
    }
}
